using System;
using System.Diagnostics;
using System.Globalization;
using System.Management.Automation.Host;
using System.Reflection;
using System.Threading;

namespace Wolfpack.Contrib.Checks.Powershell
{
    /// <summary>
    /// Serves as a class for creating a custom host. 
    /// A host provides communications between the Windows 
    /// PowerShell engine and the user.
    /// </summary>
    public class WolfpackPSHost : PSHost
    {
        private readonly Guid _hostId;
        private readonly WolfpackPSHostUserInterface _hostUi;
        private readonly CultureInfo _currentCulture;
        private readonly CultureInfo _currentUiCulture;
        //private readonly IWolfpackPowerShellHost _host;

        /// <summary>
        /// Initializes a new instance of the <see cref="WolfpackPSHost"/> class.
        /// </summary>
        /// <param name="host">The wolfpack host.</param>
        public WolfpackPSHost(IWolfpackPowerShellHost host) 
        {
            if (host == null)
            {
                throw new ArgumentNullException("host");
            }

            _currentCulture = Thread.CurrentThread.CurrentCulture;
            _currentUiCulture = Thread.CurrentThread.CurrentUICulture;

            _hostId = Guid.NewGuid();

            PSHostRawUserInterface rawUserInterface = new WolfpackPSHostRawUserInterface();
            _hostUi = new WolfpackPSHostUserInterface(host, rawUserInterface);
            //_host = host;
        }

        /// <summary>
        /// Request to end the current runspace. The Windows PowerShell 
        /// engine calls this method to request that the host application 
        /// shut down and terminate the host root runspace. 
        /// </summary>
        /// <param name="exitCode">
        /// The exit code that is used to set the host's process exit code.
        /// </param>
        public override void SetShouldExit(int exitCode)
        {
            //_host.SetShouldExit(exitCode);
        }

        /// <summary>
        /// Instructs the host to interrupt the currently running pipeline and start a new nested input loop. 
        /// </summary>
        /// <exception cref="NotImplementedException">
        /// Scripts hosted by Wolfpack must not call this method.
        /// </exception>
        public override void EnterNestedPrompt()
        {
            throw InvalidOperation();
        }

        /// <summary>
        /// Instructs the host to exit the currently running input loop. 
        /// </summary>
        /// <exception cref="NotImplementedException">
        /// Scripts hosted by Wolfpack must not call this method.
        /// </exception>
        public override void ExitNestedPrompt()
        {
            throw InvalidOperation();
        }

        /// <summary>
        /// Notifies the host that the Windows PowerShell runtime is about to 
        /// execute a legacy command-line application. A legacy application 
        /// is defined as a console-mode executable that can perform any of 
        /// the following operations: read from stdin, write to stdout, 
        /// write to stderr, or use any of the win32 console APIs. 
        /// </summary>
        public override void NotifyBeginApplication()
        {
        }

        /// <summary>
        /// Notifies the host that the Windows PowerShell engine has 
        /// completed the execution of a legacy command. A legacy application 
        /// is defined as a console-mode executable that can perform any of 
        /// the following operations: read from stdin, write to stdout, write 
        /// to stderr, or use any of the Windows console APIs. 
        /// </summary>
        public override void NotifyEndApplication()
        {
        }

        /// <summary>
        /// Gets the user-friendly name of the host.
        /// </summary>
        public override string Name
        {
            get { return "Wolfpack PowerShell Host"; }
        }

        /// <summary>
        /// Gets the version number of the host.
        /// </summary>
        public override Version Version
        {
            get { return Assembly.GetExecutingAssembly().GetName().Version; }
        }

        /// <summary>
        /// Gets the identifier that uniquely identifies this instance of the host.
        /// </summary>
        public override Guid InstanceId
        {
            get { return _hostId; }
        }

        /// <summary>
        /// Gets the implementation of the <see cref="PSHostUserInterface"/> 
        /// class that defines user interaction for this host.
        /// </summary>
        public override PSHostUserInterface UI
        {
            get { return _hostUi; }
        }

        /// <summary>
        /// Gets the culture that the runspace will use to set the current culture on new threads.
        /// </summary>
        public override CultureInfo CurrentCulture
        {
            get { return _currentCulture; }
        }

        /// <summary>
        /// Gets the UI culture that the runspace and cmdlets will use to do resource loading.
        /// </summary>
        public override CultureInfo CurrentUICulture
        {
            get { return _currentUiCulture; }
        }

        /// <summary>
        /// Raises <see cref="InvalidOperationException"/> indicating Wolfpack scripts
        /// should not call the method.
        /// </summary>
        internal static Exception InvalidOperation()
        {
            StackFrame frame = new StackTrace().GetFrame(1);
            MethodBase method = frame.GetMethod();
            Exception exception = new InvalidOperationException(string.Format(Resources.PSHostInvalidMethodCall, method.Name));
            return exception;
        }
    }
}